package donkeykong;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JPanel;
import javax.swing.Timer;
/**
 * 
 * @author Antonio Cebollada, Miguel Castillo, José Ignacio Castro
 *
 */
public class UltimoNivel extends JPanel{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	/** Imagen del nivel/pantalla  **/
	private Image imagenFondo;
	/** Referencia al DK **/
	private DonkeyKong dk;
	/** Referencia a Mario **/
	private Mario mario;
	/** Referencia a Pauline **/
	private Pauline pauline;
	/** Timer que cada cierto tiempo, enviará un evento Action **/
	private Timer t;
	/** Clip que permite iniciar o parar la musica, entre otras opciones **/
	private static Clip clickClip;
	/** Stream de la musica que suena**/	
	private AudioInputStream musicaFondo;
	/** Thread que se utiliza para lanzar un codigo en segundo plano **/
	private Thread thread=null;
	/** Matriz donde se almacena para cada plataforma si ha sido ya visitada **/
	private static boolean[][] Plataformas= new boolean[4][2];
	/**Variable que evita que se tome una plataforma como una escalera **/
	private boolean nobajar=false;
	/** Variable que congela a mario (se usa para cuando se ha pasado por todas las plataformas **/
	private boolean congelado=false;
	/** Variable que ajusta la dificultad de la pantalla **/
	private int nvDificultad;
	/** Variable que hace referencia a la puntuación total del nivel **/
	private Puntuacion_total score;
	/** Array que almacena la lista de espectros del nivel **/
	private ArrayList<Espectro> espectros;
	/** Matriz que almacena las plataformas especiale del nivel con su posición (x e y) **/
	private static Sueloespecial[][] ConjPlataformas;
	/** Variables que hacen referencia a los dos mazos**/
	private Mazo mazo,mazo2;
	/** Objetos bonus de la pantalla **/
	private Objeto objeto1, objeto2;
	
	private boolean terminar;
	
	/** Constructor
	 * 
	 * @param vidas			: vidas de Mario
	 * @param altadificultad: dificultad del juego alta (true) o baja (false)
 	 * @param multijugador  : multijugador si true, unijugador si false
	 */
	public UltimoNivel(int vidas, int nivelDificultad,Puntuacion_total pt) {
		try {
			
			/** Inicializacion de los espectros **/
			espectros = new ArrayList<Espectro>();
			/** Colocar a Mario en la posicion correspondiente **/
			mario = new Mario(130,0,3,vidas);
			mario.setPosicion_y(564+mario.getHeight());
			/**Colocar suelo que se cae en las posiciones correspondientes**/
			ConjPlataformas=ColocarSuelo();
			nvDificultad = nivelDificultad;
			Puntuacion_total pt2 = new Puntuacion_total(pt.getTECLA_ABAJO(),pt.getTECLA_ARRIBA(),pt.getTECLA_DERECHA(),pt.getTECLA_IZQUIERDA(),pt.getTECLA_SALTO(),pt.getTECLA_START(),nvDificultad);

			score = pt2;
			score.setMario(mario);
			score.ReiniciarTiempo();
			score.añadirPuntuacion(pt.obtenerPuntuacion());
			Thread TpuntuacionTotal = new Thread(score);
			TpuntuacionTotal.setName("PUNTUACIONTOTAL");
			TpuntuacionTotal.start();
			
			
			imagenFondo = ImageIO.read(new File("./pantallas/nivel_3.png"));
			/** Colocar al DK en la posicion correspondiente **/
			dk = new DonkeyKong(340,112,3,(BufferedImage)imagenFondo,null,mario,espectros, score); 
			/** Lanzamiento del thread de DK **/
			Thread Tdk = new Thread(dk);
			Tdk.start();
			pauline = new Pauline(230,63);
			/** Lanzamiento del thread de Pauline **/
			Thread TPauline = new Thread(pauline);
			TPauline.setName("PAULINE");
			TPauline.start();
			/** Listener de la clase **/
			ClaseListener cl = new ClaseListener();
			addKeyListener(cl);	
			/** Inicializamos mazos **/
			mazo = new Mazo(390,230,mario);
			Thread tmazo = new Thread(mazo);
			tmazo.setName("mazo1");
			mazo2 = new Mazo(60,330,mario);
			Thread tmazo2 = new Thread(mazo2);
			tmazo2.setName("mazo2");
			/** Iniciamos los threads de los mazos **/
			tmazo.start();
			tmazo2.start();
			/** Iniciamos los objetos de bonus **/
			objeto1 = new Objeto(130,166,mario, "paraguas", score);
			Thread paraguas = new Thread(objeto1);
			paraguas.start();
			
			objeto2 = new Objeto(430,563,mario, "bolso", score);
			Thread bolso = new Thread(objeto2);
			bolso.start();
			
			requestFocusInWindow();
			escucharMusicaFondo("Final_Stage", 0);
			t = new Timer(100,cl);
			t.start();
			
		} catch (IOException e) {
			e.printStackTrace();
		}	
	}
	
	
	
	
    /**
     * Metodo que se encarga de rellenar el array de plataformas (las inicializa)
     */
	private Sueloespecial[][] ColocarSuelo() throws IOException {
		int y,x;
		Sueloespecial[][] platArr = new Sueloespecial[4][2];
	   for(int nivel=0;nivel<4;nivel++){	
		   if(nivel==0){
			   y=501;
		   }
		   else if(nivel==1){
			   y=397;
		   }
		   else if (nivel==2){
			   y=292;
		   }
		   else{
			   y=188;
		   }
		for(int plataf=0;plataf<2;plataf++){
			if(plataf==0){
				x=192;
			}
			else{
				x=551;
			}
		 Sueloespecial suelo = new Sueloespecial(x, y);
		 platArr[nivel][plataf]=suelo;
		}
	   }
		return platArr;
	}





	/** Funcion paintComponent que es propia de los JPanels, que sirve para dibujar en el mismo la imagen que se quiera, entre otras opciones 
	 *  A través de este Paint, se pintaran los de los demas objetos que aparezcan en el nivel, desde Mario, DK, la princesa, los enemigos, objetos...
	 * **/
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D) g;
		g2d.drawImage(imagenFondo,0,0,null);
		
		if(!dk.isMuerto()){
			score.paintComponent(g);
		}
		/** Pintar a DK **/
		dk.paintComponent(g);
		/** Pintar a Mario **/
		/** Si DK no ha muerto se pintan mario y pauline normales **/
		//score.paintComponent(g);
		
		/** Pintar al DK **/
		if (mario.isMuriendo()){
			score.Acabar();
			dk.DKparado();
			mazo.pararSonido();
			mazo2.pararSonido();
		}
		
		if(!dk.isMuertodeltodo()){			
		mario.paintComponent(g);
		pauline.paintComponent(g);
		
		if (mazo.isActivo()){
			mazo.paintComponent(g);
		}

		if (mazo2.isActivo()){
			mazo2.paintComponent(g);
		}
		if (objeto1.isActivo()){
			objeto1.paintComponent(g);
		}
		
		if (objeto2.isActivo()){
			objeto2.paintComponent(g);
		}
		if (!espectros.isEmpty()){
			if (!terminar){
				for (int i=0;i<espectros.size();i++){
					if (mario.isMuriendo()){
						espectros.get(i).Acabar();
					}			
					if (mario.isInvencible()){
						espectros.get(i).Alerta();
					}else{
						espectros.get(i).Descanso();
					}
	
					if (espectros.get(i).isAcabado()){
						espectros.remove(i);
					}
	
					if (i != espectros.size()){
						espectros.get(i).setPlataformas(Plataformas);
						espectros.get(i).paintComponent(g);
					}
				}
			}
		}
		
		}
		/** En caso contrario se pinta la pantalla de final de juego **/
		else{
			try {
					imagenFondo = ImageIO.read(new File("./pantallas/nivel_3_final_2.png"));
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		}
		
		/** Pintar las plataformas por las que aun no se haya pasado **/
		for(int i=0;i<4;i++){
			for(int k=0;k<2;k++){
			ConjPlataformas[i][k].paintComponent(g);
			}
		}
		
		/** Pintar espectros **/
		
		
		
		g2d.dispose();

	}
	
	/** Funcion para escuchar la musica de fondo del nivel **/
	public void escucharMusicaFondo(String sonido, int duracion){
		try {
			clickClip = AudioSystem.getClip();
			musicaFondo = AudioSystem.getAudioInputStream(new File("./sounds/"+sonido+".wav"));
			clickClip.open(musicaFondo);
			clickClip.loop(duracion);
			clickClip.start();
		} catch (LineUnavailableException e) {
			e.printStackTrace();
		} catch (UnsupportedAudioFileException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	

	/** Clase que implementa el listener de teclas y un listener de eventos de Timer **/
	private class ClaseListener extends KeyAdapter implements ActionListener{

		/** Numero de colores de escalera que Mario debe reconocer para poder subirla **/
		private static final int COLORES_ESCALERA = 6;
		/** Variacion de la posicion Y de Mario mientras esta subiendo/bajando una escalera **/
		private static final int INCREMENTO_ESCALERAS = 4;
		/** Variables que indican si Mario se esta moviendo hacia la izquierda o hacia la derecha **/
		private boolean moviendoIzquierda, moviendoDerecha;
		/** Variable que indica si Mario esta muerto **/
		private boolean finalmentemuerto=false;
		/** Teclas de movimiento y accion (salto **/
		private int 
				TECLA_ARRIBA=KeyEvent.VK_W,
				TECLA_ABAJO=KeyEvent.VK_S,
				TECLA_DERECHA=KeyEvent.VK_D,
				TECLA_IZQUIERDA=KeyEvent.VK_A,
				TECLA_SALTAR=KeyEvent.VK_SPACE;
		
		public ClaseListener(){
			TECLA_ARRIBA=score.getTECLA_ARRIBA();
			TECLA_ABAJO=score.getTECLA_ABAJO();
			TECLA_DERECHA=score.getTECLA_DERECHA();
			TECLA_IZQUIERDA=score.getTECLA_IZQUIERDA();
			TECLA_SALTAR=score.getTECLA_SALTO();
		}
		
		/**Si se presiona una tecla**/
		public void keyPressed(KeyEvent arg0) {
			/** Si Mario no esta muriendo **/
			if(!mario.isMuriendo()){
				 if (arg0.getKeyCode() == TECLA_SALTAR){
					 
					 /**Si no es invencible(mazo) y si no esta ya saltando ni subiendo/bajando una escalera, se puede saltar **/
					if (!mario.isInvencible()&!mario.isSaltando()&!mario.isSubiendoEscalera()&!congelado){	
							/** Parar el sonido que lleve Mario **/
							mario.pararSonido();
							/** Escuchar sonido de salto **/
							mario.escucharSonido("jump",0);
							t.start();
							/** Iniciar la clase de salto **/
							Saltar saltoMario = new Saltar(mario,imagenFondo, ConjPlataformas, Plataformas, 3, score);
							Thread T = new Thread(saltoMario);
							T.start();
							repaint();
								
					}
					
				}
				if (arg0.getKeyCode() == TECLA_IZQUIERDA){
					/** SI no esta ya saltando, ni moviendose, ni subiendo una escalera **/
					if (!mario.isSaltando()&!mario.isMoviendose()&!mario.isSubiendoEscalera()&!congelado){
						/** Comprobar que no hay colision por la izquierda **/
						if (!mario.detectarColision_izq(mario.getEsquina())){
							/** Modificar variables de sentido de andar **/
							moviendoIzquierda=true;
							moviendoDerecha=false;
							mario.MostrarParadoIzq();
							
							/** Comprobar el suelo, esta funcion es la que indica en todo momento lo que debe hacer Mario con la pantalla **/
							comprobarSuelo(mario.getCentroMario(),(BufferedImage) imagenFondo);
							repaint();
							/** Escuchar sonido de andar **/
							mario.escucharSonido("walking",Clip.LOOP_CONTINUOUSLY);
							t.start();
							
							mario.moviendose();
							repaint();
							
						/** Si se detecta colision, parar el movimiento **/	
						}else{
							mario.pararse();	
							t.start();
						}
					}else{
						/** Si Mario no esta saltando ni subiendo una escalera, es decir, que ya se esta moviendo, solamente ir comprobando el suelo **/
						if(!mario.isSaltando()&!mario.isSubiendoEscalera()&!congelado)
							comprobarSuelo(mario.getCentroMario(),(BufferedImage) imagenFondo);
	
					}
	
				}
				if (arg0.getKeyCode() == TECLA_DERECHA){
					/** SI no esta ya saltando, ni moviendose, ni subiendo una escalera **/
					if (!mario.isSaltando()&!mario.isMoviendose()&!mario.isSubiendoEscalera()&!congelado){
						/** Comprobar que no hay colision por la derecha **/
						if (!mario.detectarColision_dch(mario.getEsquina())){
							/** Modificar variables de sentido de andar **/
							moviendoDerecha=true;
							moviendoIzquierda=false;
							mario.MostrarParadoDch();
							
							/** Comprobar el suelo, esta funcion es la que indica en todo momento lo que debe hacer Mario con la pantalla **/
							comprobarSuelo(mario.getCentroMario(),(BufferedImage) imagenFondo);
							repaint();
							/** Escuchar sonido de andar **/
							mario.escucharSonido("walking",Clip.LOOP_CONTINUOUSLY);
							t.start();

							mario.moviendose();
							repaint();
							
						/** Si se detecta colision, parar el movimiento **/	
						}else{
							mario.pararse();
							t.start();
						}					
					}else{
						/** Si Mario no esta saltando ni subiendo una escalera, es decir, que ya se esta moviendo, solamente ir comprobando el suelo **/
						if(!mario.isSaltando()&!mario.isSubiendoEscalera()&!congelado)
							comprobarSuelo(mario.getCentroMario(),(BufferedImage) imagenFondo);
	
					}
	
				}
				
				if (arg0.getKeyCode() == TECLA_ARRIBA){
					/** Si Mario no esta saltando ni moviendose, y tampoco es invencible(mazo), puede subir/bajar una escalera **/
					if (!mario.isInvencible()&!mario.isSaltando()&!mario.isMoviendose()&!congelado){
						BufferedImage image1 = (BufferedImage) imagenFondo;
						int coloresAzules=0;
						/** Comprobar el numero de pixeles del color de la escalera a lo largo de la imagen de Mario **/
						for (int i=mario.getPosicion_x();i<=mario.getPosicion_x()+mario.getImage().getWidth(null);i++){
							int c1 = image1.getRGB(i,mario.getPosicion_y()-1);
							Color color = new Color(c1);
							if (EsEscalera(color)){
								coloresAzules ++;
							}
						}
						/** Si el numero de colores de escalera se corresponde con el minimo para interactuar, se interactua con ella **/
						if (coloresAzules >= COLORES_ESCALERA){
							/** Mostrar animacion con las escaleras **/
							mario.animacionEscaleras();
							mario.subiendoEscalera();
							
							/** Comprobar pixel a pixel si estamos llegando a un color de suelo, que indicaria que terminamos de subir/bajar **/
							for (int j=1;j<=INCREMENTO_ESCALERAS;j++){
								mario.setPosicion_y(mario.getPosicion_y()-1);
								int c1 = image1.getRGB(mario.getCentroMario(),mario.getPosicion_y());
								Color color = new Color(c1);
								if (EsSuelo(color)){
									mario.setPosicion_y(mario.getPosicion_y()-1);
									mario.dejaEscalera();
									j=INCREMENTO_ESCALERAS;
								}
							
							}						
							
						/** Si no detectamos escalera, y estamos en una posicion de aire, es que nos hemos quedado
						*	encasillados en una escalera, al final o al principio, salvamos ese error
						**/							
						}else if (coloresAzules==0){   
							int c1 = image1.getRGB(mario.getCentroMario(),mario.getPosicion_y());
							Color color = new Color(c1);
							if (EsAire(color)){
								mario.setPosicion_y(mario.getPosicion_y()+1);
							}
						}
					}
	
				}
				if (arg0.getKeyCode() == TECLA_ABAJO){
					/** Si Mario no esta saltando ni moviendose, ni es invencible(mazo), puede subir/bajar una escalera **/
					if (!mario.isInvencible()&!mario.isSaltando()&!mario.isMoviendose()&!nobajar&!congelado){
						BufferedImage image1 = (BufferedImage) imagenFondo;
						int coloresAzules=0;
						/** Comprobar el numero de pixeles del color de la escalera a lo largo de la imagen de Mario **/
						for (int i=mario.getPosicion_x();i<=mario.getPosicion_x()+mario.getImage().getWidth(null);i++){
							int c1 = image1.getRGB(i,mario.getPosicion_y()+1);
							Color color = new Color(c1);
							if (EsEscalera(color)){
								coloresAzules ++;
							}
						}
						/** Si el numero de colores de escalera se corresponde con el minimo para interactuar, se interactua con ella **/
						if (coloresAzules >= COLORES_ESCALERA){
							/** Mostrar animacion con las escaleras **/
							mario.animacionEscaleras();
							mario.subiendoEscalera();
							
							/** Comprobar pixel a pixel si estamos llegando a un color de suelo, que indicaria que terminamos de subir/bajar **/
							for (int j=1;j<=INCREMENTO_ESCALERAS;j++){
								mario.setPosicion_y(mario.getPosicion_y()+1);
								int c1 = image1.getRGB(mario.getCentroMario(),mario.getPosicion_y());
								Color color = new Color(c1);
								if (EsSuelo(color)){
									mario.dejaEscalera();
									j=INCREMENTO_ESCALERAS;
								}
							
							}
							
						/** Si no detectamos escalera, y estamos en una posicion de aire, es que nos hemos quedado
						*	encasillados en una escalera, al final o al principio, salvamos ese error
						**/		
						}else if (coloresAzules==0){
							int c1 = image1.getRGB(mario.getCentroMario(),mario.getPosicion_y());
							Color color = new Color(c1);
							if (EsAire(color)){
								mario.setPosicion_y(mario.getPosicion_y()+1);
							}
						}

					}
				}
				
			/** Si Mario esta muerto, dejar de reproducir la musica **/
			}else{
				pararSonido();
			}
			
		}
		
		/** Funcion que se llama cuando se suelta una tecla **/
		public void keyReleased(KeyEvent arg0) {
			/** Si Mario no esta muriendo **/
			if (!mario.isMuriendo()){
				if (arg0.getKeyCode() == TECLA_DERECHA){
					/** Si Mario no esta ni saltando ni moviendose ni en una escalera **/
					if(!mario.isSaltando()&!mario.isMoviendose()&!mario.isSubiendoEscalera()&!congelado){
						mario.pararSonido();
						moviendoDerecha=false;
						mario.pararse();
						mario.MostrarParadoDch();
						/** Parar el Timer para que no siga pintando automaticamente **/
						t.restart();
						repaint();
					}else{
						if (!mario.isSaltando())
							mario.pararSonido();
						moviendoDerecha=false;
						mario.pararse();					
					}
				}
				if(arg0.getKeyCode() == TECLA_IZQUIERDA){
					/** Si Mario no esta ni saltando ni moviendose ni en una escalera **/
					if (!mario.isSaltando()&!mario.isMoviendose()&!mario.isSubiendoEscalera()&!congelado){
						mario.pararSonido();
						moviendoIzquierda=false;
						mario.pararse();
						mario.MostrarParadoIzq();
						/** Parar el Timer para que no siga pintando automaticamente **/
						t.restart();
						repaint();
					}else{
						if (!mario.isSaltando())
							mario.pararSonido();
						moviendoDerecha=false;
						mario.pararse();					
					}
				}
			/** Si Mario esta muerto, dejar de reproducir la musica **/	
			}else{
				pararSonido();
			}
		}

		/** Funcion que se encarga de repintar cada cierto tiempo y teniendo en cuenta los estados en los que se puede encontrar Mario **/
		@Override
		public void actionPerformed(ActionEvent arg0) {
			
			if (dk.reiniciarJuego){
				
				CambiarNivel();
			}else{
				/** Si no se tiene que resetear el nivel **/
				if (!mario.isResetearNivel()){
					/** Si Mario no esta muerto **/
					if(!mario.isMuriendo()){
						/** Si mario se esta moviendo pero no esta en una escalera **/
						if (mario.isMoviendose() & !mario.isSubiendoEscalera()&!mario.isSaltando()){
								/** Comprobar si se esta moviendo en izquierda o en derecha para moverlo en esa direccion y repintar **/
								if (moviendoIzquierda){
										mario.moverIzquierda();
										repaint();
								}else if (moviendoDerecha){
										mario.moverDerecha();
										repaint();
								}
								/** Si Mario no esta saltando, comprobar en todo momento el suelo **/
								if (!mario.isSaltando()&!congelado)
									comprobarSuelo(mario.getCentroMario(),(BufferedImage) imagenFondo);
			
						}
					/** Mario esta muerto, se debe dejar de reproducir la musica y ejecutar la clase Muerto, para que ejecute la
					 * secuencia de muerte de Mario.	
					 */
					}else{  
						pararSonido();
						if (!finalmentemuerto){
							mario.pararSonido();
							pararSonido();
							finalmentemuerto=true;
							Muerto muerto = new Muerto(mario);
							thread = new Thread(muerto);
							thread.start();
						}
					}
					repaint();
	
				/** Se tiene que resetear el nivel**/
				}else{
					resetearNivel();
				}
			}
			
		}

		
	}

	/** Funcion de inicializar que añade los JPanels de los objetos que aparecen en la pantalla al JFrame para que puedan pintarse correctamente **/
	public void inicializar() {
		//getParent().add(dk);
		getParent().add(mario);
		
	}





	/** Funcion de resetear nivel, elimina los JPanel innecesarios, y vuelve a ejecutar la clase Intermedio **/
	public void resetearNivel() {
		t.stop();
		/** Borrar los Threads de los enemigos que haya activos **/
		if (!espectros.isEmpty()){
			for (int i=0;i<espectros.size();i++){
				espectros.get(i).Acabar();
			}
		}
		
		getParent().remove(dk);
		getParent().remove(mario);
		Intermedio it = new Intermedio(3, mario.getVidas(), nvDificultad, score);
		Plataformas= new boolean[4][2];
		score.Acabar();
		score.pararSonido();
		mazo.Usar();
		mazo2.Usar();
		getParent().add(it);
		it.setVisible(true);
		setVisible(false);
		getParent().remove(this);
		it.requestFocusInWindow();		
	}
	
	/** Funcion de cambiar al primer nivel, elimina los JPanel innecesarios, y vuelve a ejecutar la clase Intermedio **/
	public void CambiarNivel() {
		/** Avanzar en un nivel para aumentar la dificultad en el bucle del juego **/
		nvDificultad++;
		t.stop();
		mario.pararSonido();
		/** Borrar los Threads de los enemigos que haya activos **/
		if (!espectros.isEmpty()){
			for (int i=0;i<espectros.size();i++){
				espectros.get(i).Acabar();
			}
		}
		Plataformas= new boolean[4][2];
		score.Acabar();
		score.pararSonido();
		mazo.Usar();
		mazo2.Usar();
		t.stop();
		getParent().remove(dk);
		getParent().remove(mario);
		Intermedio it = new Intermedio(1, mario.getVidas(), nvDificultad, score);
		getParent().add(it);
		it.setVisible(true);
		setVisible(false);
		getParent().remove(this);
		it.requestFocusInWindow();		
	}
	
	


	/** Funcion de comprobar suelo, sirve para poder moverse por la pantalla, poder caer, subir/bajar escaleras,etc **/
	public void comprobarSuelo(int centroMario,BufferedImage image1){
		
		int c1 = image1.getRGB(centroMario,mario.getPosicion_y());
		Color color = new Color(c1);
		

		/** Identificamos si mario esta pasando por una de las dos plataformas **/
		if((centroMario>182&&centroMario<250)||((centroMario>540&&centroMario<596))){ //Posicion de las plataformas
			

			nobajar=true;
			int nivel=0,plataf=0;
			int limite1=0;
			int limite2=0;
			/** Miramos la plataforma por la que esta pasando **/
			if((centroMario>182&&centroMario<250)){	//Plataformas de la izquierda				
				plataf=0;
				limite1=215;
				limite2=192;
			}
			else if((centroMario>540&&centroMario<596)){	//Plataformas de la derecha
				plataf=1;
				limite1=577;
				limite2=551;
			}
			else{
				return;
			}
			/** Miramos el nivel en el que esta la plataforma **/
			if(mario.getPosicion_y()==480){	
				nivel=0;
			}
			else if(mario.getPosicion_y()==376){				
				nivel=1;
			}
			else if (mario.getPosicion_y()==272){
				nivel=2;
			}
			else if(mario.getPosicion_y()==167){
				nivel=3;
			}
			else{
				return;
			}
			/** Miramos si ya habia pasado o no por esa plataforma **/
			if(((mario.MirandoDcha()&&(centroMario>=limite1))||(!mario.MirandoDcha()&&(centroMario<=limite2)))&&(Plataformas[nivel][plataf]==false)){
				Sueloespecial.escucharMusicaFondo("item_points", 0);
				score.añadirPuntuacion(100);
				Puntuacion_imagen pi = new Puntuacion_imagen(mario, 4);
				Thread t = new Thread(pi);
				t.start();
				Plataformas[nivel][plataf]=true;
				ConjPlataformas[nivel][plataf].setPosicion_x(-1);
				ConjPlataformas[nivel][plataf].setPosicion_y(-1);
				/** Comprobamos si esta plataforma era la ultima que quedaba**/
				terminar = ComprobarPlataformas();
				/** Si era la ultima iniciamos el fin del juego **/
				if (terminar){
						pararSonido();
						/**No seguir con el timer de la puntuacion **/
						score.Acabar();
						score.pararSonido();
						/** Borrar los Threads de los enemigos que haya activos **/
						if (!espectros.isEmpty()){
							for (int i=0;i<espectros.size();i++){
								espectros.get(i).Acabar();
							}
						}
						/** Quitar los mazos **/
						mazo.Usar();
						mazo2.Usar();
						objeto1.Usar();
						objeto2.Usar();
						/** DK muere **/
						dk.morir();						
					try {
						/** Cambiamos la imagen de fondo a la de caida de DK y congelamos a mario **/
						imagenFondo = ImageIO.read(new File("./pantallas/nivel_3_final_1.png"));
						congelado=true;					
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				return;
			}
					
			/** Si la plataforma por la que pasamos ya habia sido visitada iniciamos la caida **/		
			if(Plataformas[nivel][plataf]){
				
				c1 = image1.getRGB(centroMario,mario.getPosicion_y());
				color = new Color(c1);
				int caida=0;
				/** Mientras el color no sea el del suelo, bajar **/
				while (!(EsSuelo(color))){
					 
					 mario.setPosicion_y(mario.getPosicion_y()+1);	
					 c1 = image1.getRGB(centroMario,mario.getPosicion_y());
					 color = new Color(c1);
					 caida++;
				}
				/** Si la caida es muy grande, Mario muere **/
				if (caida>20){
					pararSonido();
					mario.Muriendo();
					mario.pararSonido();
				}			
			
			}			
			
		}
		/** No esta en la posicion de plataformas **/
		else{
		nobajar=false;
		/** Comprobar el suelo si es negro, (color del aire) , es bajar posicion 'y' hasta encontrar color de suelo **/
		if ((EsAire(color))){
			c1 = image1.getRGB(centroMario,mario.getPosicion_y());
			color = new Color(c1);
			int caida=0;
			/** Mientras el color no sea el del suelo, bajar **/
			while (!(EsSuelo(color))){
				 
				 mario.setPosicion_y(mario.getPosicion_y()+1);	
				 c1 = image1.getRGB(centroMario,mario.getPosicion_y());
				 color = new Color(c1);
				 caida++;
			}
			/** Si la caida es muy grande, Mario muere **/
			if (caida>20){
				pararSonido();
				mario.Muriendo();
				mario.pararSonido();
			}			
		/** Si no es negro ni es el color del suelo, sera subir posicion 'y' hasta encontrar aire (o escalera) **/
		}else if (!EsSuelo(color)){
			c1 = image1.getRGB(centroMario,mario.getPosicion_y());
			color = new Color(c1);
			boolean seguirSubiendo=true;
			 if ((EsAire(color))|((EsEscalera(color)))){
				 seguirSubiendo=false;
			 }
			
			/** Mientras no se llegue a color de aire o escalera, subir a Mario **/
			while (seguirSubiendo){
		 	 mario.setPosicion_y(mario.getPosicion_y()-1);	
			 c1 = image1.getRGB(centroMario,mario.getPosicion_y());
			 color = new Color(c1);
			 if ((EsAire(color))|((EsEscalera(color)))){
				 seguirSubiendo=false;
			 }
			}
	
		}
		}
		
		
	}
	/**
	 * Función que comprueba si ya se han visitado todas las plataformas
	 * @return boolean
	 */
	private boolean ComprobarPlataformas() {
		//TODO
		boolean acabado=true;
		
		for (int i = 0; i<=3;i++){
			for (int k = 0;k<=1;k++){
				if(!Plataformas[i][k]){
					acabado=false;
				}
			}
		}		
		return acabado;		
	}





	/** Funcion que dado un color, indica si es el color del suelo **/
	public boolean EsSuelo(Color color){
		int plataf;
		int nivel;
		
		/** Comprobamos si esta en alguna de las plataformas **/
		if (!(color.getRed()>23 & color.getGreen()<58 & color.getBlue()>250)){
			if((mario.getCentroMario()>182&&mario.getCentroMario()<250)){	//Plataformas de la izquierda
				
					plataf=0;
			}
				else if((mario.getCentroMario()>540&&mario.getCentroMario()<590)){	//Plataformas de la derecha
				
					plataf=1;
					
				}
				else{
					return false;
				}
				/**Miramos el nivel en el que esta*/
				if(mario.getPosicion_y()==480){	
					nivel=0;
				}
				else if(mario.getPosicion_y()==376){
					nivel=1;
				}
				else if (mario.getPosicion_y()==272){
					nivel=2;
				}
				else if(mario.getPosicion_y()==167){
					nivel=3;
				}
				else{
					return false;
				}
				if (!Plataformas[nivel][plataf]){
					return true;				
				}
				else{
					return false;
				}
		}
		
		return true;
	}
	
	/** Funcion que dado un color, indica si es el color del aire **/
	public boolean EsAire(Color color){
		return (color.getRed()==0 & color.getGreen()==0 & color.getBlue()==0);
	}
	
	/** Funcion que dado un color, indica si es el color de una escalera **/
	public boolean EsEscalera(Color color){
		return (color.getRed()<=252 & color.getGreen()>=160 & color.getBlue()>=68);
	}	
	
	
	/** Funcion que se utiliza para parar el sonido, si esta activado **/
	public void pararSonido(){
		if(clickClip != null){
			clickClip.stop();
			clickClip.close();
		}
	}
	
}
